package com.cfjjc.gz.common.dao;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.dao.DataAccessException;
import com.cfjjc.gz.common.cache.CacheUtil;
import com.cfjjc.gz.common.exception.OTSException;
import com.cfjjc.gz.common.util.paged.base.LimitedList;
import com.cfjjc.gz.common.util.spring.orm.ibatis.SqlMapDaoSupportPlus;

/**
 * 缺省的dao基类<br>
 * <li>处理所有的数据访问,需要传入值对象参数及命名空间</li>
 * 
 */
public class DefaultDAO extends SqlMapDaoSupportPlus {

	/**
	 * 缺省的查询语句的名称
	 */
	public static final String QUERY_NAME = "query";

	/**
	 * 缺省的查询总记录个数语句的名称
	 */
	public static final String QUERY_COUNT_NAME = "query_COUNT";

	/**
	 * 缺省的插入语句的名称
	 */
	public static final String INSERT_NAME = "insert";

	/**
	 * 缺省的更新语句的名称
	 */
	public static final String UPDATE_NAME = "update";

	/**
	 * 缺省的删除语句的名称
	 */
	public static final String DELETE_NAME = "delete";

	/**
	 * 构造函数
	 */
	public DefaultDAO() {
		super();
	}

	/**
	 * 查询对象,使用缺省命名的sql语句
	 * 
	 * @param param
	 *            参数
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的语句
	 */
	public Object queryObject(Object param, String nameSpace)
			throws OTSException {
		return queryObject(param, nameSpace, null);
	}

	/**
	 * 查询对象
	 * 
	 * @param param
	 *            参数
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的语句
	 * @return 结果对象
	 * @throws OTSException
	 */
	public Object queryObject(Object param, String nameSpace, String sqlName)
			throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(QUERY_NAME);
		} else {
			statement.append(sqlName);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行query object请求,语句名称=" + statement.toString());
		}
		
		Object obj = null;
		try {
			obj = getSqlMapClientTemplate().queryForObject(statement.toString(),
					param);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("查询数据时发生错误,请检查输入是否正确");
		}
		return obj;
	}

	/**
	 * 分页查询
	 * 
	 * @param param
	 *            参数
	 * @param records
	 *            分页记录
	 * @param nameSpace
	 *            命名空间
	 */
	public void queryPagedList(Object param, LimitedList records,
			String nameSpace) throws OTSException {
		queryPagedList(param, records, nameSpace, null);
	}

	/**
	 * 分页查询
	 * 
	 * @param param
	 *            参数
	 * @param records
	 *            分页记录
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的语句
	 * @throws OTSException
	 */
	public void queryPagedList(Object param, LimitedList records,
			String nameSpace, String sqlName) throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer query = new StringBuffer();
		query.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			query.append(QUERY_NAME);
		} else {
			query.append(sqlName);
		}
		String queryCount = query.toString() + "_COUNT";

		if (records.getTotalNum() == -1) {
			records.setParam(param);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行查询分页列表请求,语句名称=" + query.toString());
		}
		
		try {
			getSqlMapClientTemplate().query(query.toString(), queryCount, records);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("查询数据时发生错误,请检查输入是否正确");
		}
	}

	/**
	 * 查询列表,使用缺省命名的sql语句
	 * 
	 * @param param
	 *            参数
	 * @param nameSpace
	 *            命名空间
	 */
	public List queryList(Object param, String nameSpace)
			throws OTSException {
		return queryList(param, nameSpace, null);
	}

	/**
	 * 查询列表
	 * 
	 * @param param
	 *            参数
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的语句
	 * @return 结果列表
	 * @throws OTSException
	 */
	public List queryList(Object param, String nameSpace, String sqlName)
			throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(QUERY_NAME);
		} else {
			statement.append(sqlName);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行query list请求,语句名称=" + statement.toString());
		}
		
		List rs = null;
		try {
			rs = getSqlMapClientTemplate().queryForList(statement.toString(), param);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("查询数据时发生错误,请检查输入是否正确");
		}
		return rs;
	}

	/**
	 * 查询map（结果就是map中间的map）
	 * 
	 * @param param
	 *            参数
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的语句
	 * @return 结果列表
	 * @throws OTSException
	 */
	public Map queryMap(Object param, String nameSpace, String sqlName,
			String key) throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(QUERY_NAME);
		} else {
			statement.append(sqlName);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行query list请求,语句名称=" + statement.toString());
		}
		
		Map map = null;
		try {
			map = getSqlMapClientTemplate().queryForMap(statement.toString(),
					param, key);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("查询数据时发生错误,请检查输入是否正确");
		}
		return map;
	}

	/**
	 * 查询,结果为map
	 * 
	 * @param param
	 *            参数
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的语句
	 * @return 结果列表
	 * @throws OTSException
	 */
	public Map queryLimitedMap(Object param, String nameSpace, String sqlName,
			String key, int start, int maxResults) throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(QUERY_NAME);
		} else {
			statement.append(sqlName);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行query list请求,语句名称=" + statement.toString());
		}
		
		List limitedList = null;
		try {
			limitedList = getSqlMapClientTemplate().queryForList(
					statement.toString(), param, start, maxResults);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("查询数据时发生错误,请检查输入是否正确");
		}
		
		Map m = new HashMap();
		for (Iterator i = limitedList.iterator(); i.hasNext();) {
			Object row = i.next();
			try {
				Object key_property = BeanUtils.getProperty(row, key);
				m.put(key_property, row);
			} catch (Exception e) {
				logger.error(e);
				throw new OTSException("发生内部错误,请联系管理员");
			}

		}
		return m;
	}

	/**
	 * 插入,使用缺省命名的sql语句
	 */
	public Object insert(Object param, String nameSpace)
			throws OTSException {
		return insert(param, nameSpace, null);
	}

	/**
	 * 插入
	 * 
	 * @param param
	 *            参数对象
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的sql名称
	 * @return 生成的主键值
	 * @throws OTSException
	 */
	public Object insert(Object param, String nameSpace, String sqlName)
			throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(INSERT_NAME);
		} else {
			statement.append(sqlName);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("执行insert请求,语句名称=" + statement.toString());
		}
		Object result = null;
		try {
			result = getSqlMapClientTemplate().insert(statement.toString(),
					param);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("保存数据时发生错误,请检查输入是否正确(输入内容是否过长,必填字段是否为空等)");
		}

		// 如果当前操作的表已经缓存,还需要更新缓存数据
		if (CacheUtil.needRefreshCache(nameSpace)) {
			try {
				CacheUtil.refreshCache(nameSpace,
						CacheUtil.CACHE_REFRESH_TYPE_INSERT, param);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				throw new OTSException("更新系统缓存失败," + e.getMessage());
			}

		}

		return result;
	}

	/**
	 * 更新,使用缺省命名的sql语句
	 */
	public int update(Object param, String nameSpace)
			throws OTSException {
		return update(param, nameSpace, null);
	}

	/**
	 * 更新
	 * 
	 * @param param
	 *            参数对象
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的sql名称
	 * @throws OTSException
	 */
	public int update(Object param, String nameSpace, String sqlName)
			throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(UPDATE_NAME);
		} else {
			statement.append(sqlName);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行update请求,语句名称=" + statement.toString());
		}
		int result = 0;
		try {
			result = getSqlMapClientTemplate().update(statement.toString(),
					param);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("保存数据时发生错误,请检查输入是否正确(输入内容是否过长,必填字段是否为空等)");
		}
		
		if (CacheUtil.needRefreshCache(nameSpace)) {	// 如果当前操作的表已经缓存,还需要更新缓存数据
			Object tocache = queryObject(param, nameSpace);
			CacheUtil.refreshCache(nameSpace,
					CacheUtil.CACHE_REFRESH_TYPE_UPDATE, tocache);
		}
		return result;
	}

	/**
	 * 删除,使用缺省命名的sql语句
	 */
	public int delete(Object param, String nameSpace)
			throws OTSException {
		return delete(param, nameSpace, null);
	}

	/**
	 * 删除
	 * 
	 * @param param
	 *            参数对象
	 * @param nameSpace
	 *            命名空间
	 * @param sqlName
	 *            指定需要执行的sql名称
	 * @throws OTSException
	 */
	public int delete(Object param, String nameSpace, String sqlName)
			throws OTSException {
		/**
		 * 采用命名空间访问
		 */
		StringBuffer statement = new StringBuffer();
		statement.append(nameSpace.toUpperCase()).append(".");
		if (sqlName == null || sqlName.equals("")) {
			statement.append(DELETE_NAME);
		} else {
			statement.append(sqlName);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("执行delete请求,语句名称=" + statement.toString());
		}
		
		int result;
		try {
			result = getSqlMapClientTemplate().delete(statement.toString(),
					param);
		} catch (DataAccessException e) {
			logger.error(e.getMessage(), e);
			throw new OTSException("删除数据时发生错误,请检查输入是否正确");
		}

		// 如果当前操作的表已经缓存,还需要更新缓存数据
		if (CacheUtil.needRefreshCache(nameSpace)) {
			CacheUtil.refreshCache(nameSpace,
					CacheUtil.CACHE_REFRESH_TYPE_DELETE, param);
		}
		return result;
	}
}
